#!/usr/bin/env python
# -*- coding: utf-8 -*-
from copy import deepcopy
from tool.kxianhuizhi2 import open_kxiantu, load_data
from tool.gongju import *
from tool.zhibiao import ma_z, ema_z, atr_z
from tool.yujingWin import YuyinBobao  # 导入语音播报
import tqsdk.ta as tqzb
import tool.MyTT as myttzb
import talib


def 想要的策略名称_v1(cl):
    """
    策略编写模版，此处可注释为自己策略逻辑
    :param cl策略类
    :param cl.klines: k线数据，为df表，0层数据用klines[0]表示订阅的第一个合约，klines[1]是订阅的第二个合约
    :param cl.openingdata: 交易数据，为字典，里面有持仓状态，理论持仓数量，开仓价格，开仓时间等，
    :param cl.zhanghu: 账户列表，按软件登录账户顺序排列
    :param cl.jiaoyishezhi: 为交易设置数据，算法交易，交易合约，其他功能参数都在里面
    :param cl.jiaoyiqidong: 是否启动了交易，为TRUS表示启动
    :return: 输出要在软件上和K线图上显示的指标，设置为"w"为不显示，运行策略时刻节约计算机资源
    """
    # 数据提取区
    Open = cl.klines[0].open.values  # 开盘价np列表
    High = cl.klines[0].high.values   # 最高价np列表
    Low = cl.klines[0].low.values  # 最低价np列表
    Close = cl.klines[0].close.values  # 收盘价np列表
    Datetime = cl.klines[0].datetime.values  # 日期时间序列
    canshu = [cl.jiaoyiqidong, cl.zhanghu, cl.jiaoyishezhi, cl.openingdata, Datetime]  # 传递给交易函数用于交易
    riqi = cl.get_riqi(0)  # 当前k线日期
    shijian = cl.get_shijian(0)  # 当前k线时间
    chicang = cl.openingdata['kaicangzhuangtai'] * cl.openingdata['kaicangshuliang']   # 持仓状态和持仓数量
    kaicangjia = cl.openingdata['kaicangjia']  # 开仓价格

    # 参数设置区
    ss = cl.jiaoyishezhi[5][0]  # 开仓数量
    n1 = cl.jiaoyishezhi[5][1]  # ma1周期
    账户 = cl.zhanghu[cl.jiaoyishezhi[0][0]]  # 设置的交易账户对象
    交易合约 = cl.jiaoyishezhi[3][0]
    # 全局变量的初始化，为空的时候执行
    if '最小变动' not in cl.sjb:  # 每次策略初始化或更新数据时执行一次，用于在策略运行期间想持久化的数据
        cl.sjb['最小变动'] = 账户.get_zuixiaobiandong(交易合约)

    if cl.shangcishijian != Datetime[-1]:  # 更新k线时执行，一般用与收盘需要计算的指标
        pass

    # 指标计算区
    ma1 = ema_z(Close[-300:], n1)

    # # 用ma
    # ma1 = ma_z(Close[-300:], n1)

    # 交易逻辑执行区
    if chicang <= 0 and Close[-2] > ma1[-2]:
        # Buy(ss, Open[-1], canshu)
        pass
    else:
        if chicang >= 0 and Close[-2] < ma1[-2]:
            # SellShort(ss,  Open[-1], canshu)
            pass

    return ma1[-2], "w", kaicangjia, chicang  # 此处输出的指标会在k线图中和监控界面中显示


def 测试用策略_v1(cl):
    """
    测试用
    :param cl策略类
    :param cl.klines: k线数据，为df表，0层数据用klines[0]表示订阅的第一个合约，klines[1]是订阅的第二个合约
    :param cl.openingdata: 交易数据，为字典，里面有持仓状态，理论持仓数量，开仓价格，开仓时间等，
    :param cl.zhanghu: 账户列表，按软件登录账户顺序排列
    :param cl.jiaoyishezhi: 为交易设置数据，算法交易，交易合约，其他功能参数都在里面
    :param cl.jiaoyiqidong: 是否启动了交易，为TRUS表示启动
    :return: 输出要在软件上和K线图上显示的指标，设置为"w"为不显示，运行策略时刻节约计算机资源
    """
    # 数据提取区
    Open = cl.klines[0].open.values  # 开盘价np列表
    High = cl.klines[0].high.values   # 最高价np列表
    Low = cl.klines[0].low.values  # 最低价np列表
    Close = cl.klines[0].close.values  # 收盘价np列表
    Datetime = cl.klines[0].datetime.values  # 日期时间序列
    canshu = [cl.jiaoyiqidong, cl.zhanghu, cl.jiaoyishezhi, cl.openingdata, Datetime]  # 传递给交易函数用于交易
    riqi = cl.get_riqi(0)  # 当前k线日期
    shijian = cl.get_shijian(0)  # 当前k线时间
    chicang = cl.openingdata['kaicangzhuangtai'] * cl.openingdata['kaicangshuliang']   # 持仓状态和持仓数量
    kaicangjia = cl.openingdata['kaicangjia']  # 开仓价格

    # 参数设置区
    ss = cl.jiaoyishezhi[5][0]  # 开仓数量
    n1 = cl.jiaoyishezhi[5][1]  # ma1周期
    n2 = cl.jiaoyishezhi[5][2]  # ma2周期

    账户 = cl.zhanghu[cl.jiaoyishezhi[0][0]]  # 设置的交易账户对象
    交易合约 = cl.jiaoyishezhi[3][0]
    # 全局变量的初始化，为空的时候执行
    if '最小变动' not in cl.sjb:  # 每次策略初始化或更新数据时执行一次，用于在策略运行期间想持久化的数据
        cl.sjb['最小变动'] = 账户.get_zuixiaobiandong(交易合约)
        cl.sjb["提取名称"] = GetProduct(交易合约)
        cl.sjb["是否有夜盘"] = YouyepanPinzhong(交易合约)
        cl.sjb["开盘时间"] = KaipanShijian(交易合约)
        cl.sjb["tick"] = DuquRedis_HQ(交易合约)
        cl.sjb['是否在交易时间'] = get_shifouzaijiaoyishijian(交易合约)
        cl.sjb['算法交易状态'] = suanfa_kaiguan_zhuangtai()
        # cl.sjb['ma1'] = ema_z(Close[-300:], n1)
        # cl.sjb['ma2'] = ema_z(Close[-300:], n2)


    # 指标计算区
    ma1 = ema_z(Close[-300:], n1)
    ma2 = ema_z(Close[-300:], n2)

    # cicang = chazhaoheyue_duiyingchicang(账户.df_cc, 交易合约)[0]

    if cl.shangcishijian != Datetime[-1]:  # 更新k线时执行，一般用与收盘需要计算的指标
        pass

        suanfa_kaiguan_kongzhi(False)

        # # 用ma
        # ma1 = ma_z(Close[-300:], n1)

        # 交易逻辑执行区
        if chicang <= 0 and Close[-2] > ma2[-2] and Close[-3] < ma2[-3]:
            Buy(ss, Open[-1], canshu)
            # print('平空开多', riqi,shijian, ss, Open[-1])
        else:
            if chicang >= 0 and Close[-2] < ma2[-2] and Close[-3] > ma2[-3]:
                SellShort(ss,  Open[-1], canshu)
                # print('平多开空', riqi, shijian, ss, Open[-1])

        if  cl.shangcikaicangjuli > 0:
            if Close[-4] < Open[-4] and chicang > 0 and Close[-2] > Open[-2] and Close[-3] > Open[-3]:
                Buy_jjc(ss, Open[-1], canshu)
                # print('平空开多', riqi,shijian, ss, Open[-1])
            else:
                if Close[-4] > Open[-4] and chicang < 0 and Close[-2] < Open[-2] and Close[-3] < Open[-3]:
                    SellShort_jjc(ss,  Open[-1], canshu)
                    # print('平多开空', riqi, shijian, ss, Open[-1])

            if chicang > 0 and Open[-1] < ma1[-2]:
                MubiaoCangwei(0, Open[-1], canshu)
            else:
                if chicang < 0 and Open[-1] > ma1[-2]:
                    MubiaoCangwei(0,  Open[-1], canshu)

    kchzq = cl.shoucipingcangjuli+2
    gd = High[-kchzq:].max()
    kchzq = cl.shoucikaicangjuli + 2
    kcgd = High[-kchzq:].max()
    # dd = Low[-kchzq:].min()
    # if cl.thread_name == 0 and len(cl.klines[0]) > 700: print(kuazhouqi_1d(cl.klines[0], 3))
    # 软件名 = cl.name.split(".")[0] + ".celue"
    # shujuku.publish(软件名, "螺纹开多")  # 发送一个预警信息到预警中心，预警中心会弹出
    # YuyinBobao("螺纹，开仓了， 开仓了")
    # ma1[-2], cl.shangcikaicangjuli, cl.shangcipingcangjuli, chicang,  ma2[-2], ma1[-2]
    return  cl.shoucipingcangjuli, gd, kcgd, chicang  # 此处输出的指标会在k线图中和监控界面中显示


def 三均线策略_v1(cl):
    """
    此策略为双均线演示策略
    :param cl策略类
    :param cl.klines: k线数据，为df表，0层数据用klines[0]表示
    :param cl.openingdata: 交易数据，为字典，里面有持仓状态，理论持仓数量，开仓价格，开仓时间等
    :param cl.zhanghu: 账户列表
    :param cl.jiaoyishezhi: 为交易设置数据，算法交易，交易合约，其他功能参数都在里面
    :param cl.jiaoyiqidong: 是否启动了交易，为TRUS表示启动
    :return: 输出要在软件上显示的指标
    """
    # 数据提取区
    Open = cl.klines[0].open.values  # 开盘价np列表
    High = cl.klines[0].high.values   # 最高价np列表
    Low = cl.klines[0].low.values  # 最低价np列表
    Close = cl.klines[0].close.values  # 收盘价np列表，Close[-1]这样为最新价
    canshu = [cl.jiaoyiqidong, cl.zhanghu, cl.jiaoyishezhi, cl.openingdata, cl.klines[0].datetime.values]  # 传递给交易函数用于交易
    riqi = cl.get_riqi(1)
    shijian = cl.get_shijian(1)
    chicang = cl.openingdata['kaicangzhuangtai']  # 持仓状态和持仓数量
    chicangshuliang = cl.openingdata['kaicangshuliang']  # 理论持仓数量
    kaicangjia = cl.openingdata['kaicangjia']  # 开仓价格

    # 参数设置区
    ss = cl.jiaoyishezhi[5][0]  # 开仓数量
    n1 = cl.jiaoyishezhi[5][1]  # ma1周期
    n2 = cl.jiaoyishezhi[5][2]  # ma2周期
    n3 = cl.jiaoyishezhi[5][3]  # ma3周期
    # 指标计算区
    ma1 = ema_z(Close[-300:], n1)
    ma2 = ema_z(Close[-300:], n2)
    ma3 = ema_z(Close[-300:], n3)
    # # 用ma
    # ma1 = ma_z(Close[-300:], n1)
    # ma2 = ma_z(Close[-300:], n2)
    # ma3 = ema_z(Close[-300:], n2)

    # 交易逻辑执行区
    if chicang <= 0 and ma1[-2] > ma2[-2] and ma2[-2] > ma3[-2]:
        Buy(ss, Open[-1], canshu)
    else:
        if chicang >= 0 and ma1[-2] < ma2[-2] and ma2[-2] < ma3[-2]:
            SellShort(ss,  Open[-1], canshu)

    return ma1[-2], ma2[-2], ma3[-2], 0  # 此处输出的指标会在k线图中和监控界面中显示


def 双均线策略_v1(cl):
    """
    此策略为双均线演示策略
    :param cl策略类
    :param cl.klines: k线数据，为df表，0层数据用klines[0]表示
    :param cl.openingdata: 交易数据，为字典，里面有持仓状态，理论持仓数量，开仓价格，开仓时间等
    :param cl.zhanghu: 账户列表
    :param cl.jiaoyishezhi: 为交易设置数据，算法交易，交易合约，其他功能参数都在里面
    :param cl.jiaoyiqidong: 是否启动了交易，为TRUS表示启动
    :return: 输出要在软件上显示的指标
    """
    # 数据提取区
    Open = cl.klines[0].open.values  # 开盘价np列表
    High = cl.klines[0].high.values   # 最高价np列表
    Low = cl.klines[0].low.values  # 最低价np列表
    Close = cl.klines[0].close.values  # 收盘价np列表，Close[-1]这样为最新价
    canshu = [cl.jiaoyiqidong, cl.zhanghu, cl.jiaoyishezhi, cl.openingdata, cl.klines[0].datetime.values]  # 传递给交易函数用于交易
    riqi = cl.get_riqi(1)
    shijian = cl.get_shijian(1)
    chicang = cl.openingdata['kaicangzhuangtai']  # 持仓状态和持仓数量
    chicangshuliang = cl.openingdata['kaicangshuliang']  # 理论持仓数量
    kaicangjia = cl.openingdata['kaicangjia']  # 开仓价格

    # 参数设置区
    ss = cl.jiaoyishezhi[5][0]  # 开仓数量
    n1 = cl.jiaoyishezhi[5][1]  # ma1周期
    n2 = cl.jiaoyishezhi[5][2]  # ma2周期
    # 指标计算区
    ma1 = ema_z(Close[-300:], n1)
    ma2 = ema_z(Close[-300:], n2)
    # # 用ma
    # ma1 = ma_z(Close[-300:], n1)
    # ma2 = ma_z(Close[-300:], n2)

    # 交易逻辑执行区
    if chicang <= 0 and ma1[-2] > ma2[-2]:
        Buy(ss, Open[-1], canshu)
    else:
        if chicang >= 0 and ma1[-2] < ma2[-2]:
            SellShort(ss,  Open[-1], canshu)

    return ma1[-2], ma2[-2], 0, 0  # 此处输出的指标会在k线图中和监控界面中显示


def 单均线策略_v1(cl):
    """
    此策略为单均线策略
    :param cl策略类
    :param cl.klines: k线数据，为df表，0层数据用klines[0]表示
    :param cl.openingdata: 交易数据，为字典，里面有持仓状态，理论持仓数量，开仓价格，开仓时间等
    :param cl.zhanghu: 账户列表
    :param cl.jiaoyishezhi: 为交易设置数据，算法交易，交易合约，其他功能参数都在里面
    :param cl.jiaoyiqidong: 是否启动了交易，为TRUS表示启动
    :return: 输出要在软件上显示的指标
    """
    # 数据提取区
    Open = cl.klines[0].open.values  # 开盘价np列表
    # High = cl.klines[0].high.values   # 最高价np列表
    # Low = cl.klines[0].low.values  # 最低价np列表
    Close = cl.klines[0].close.values  # 收盘价np列表，Close[-1]这样为最新价
    Datetime = cl.klines[0].datetime.values  # 日期时间np列表，为时间戳
    canshu = [cl.jiaoyiqidong, cl.zhanghu, cl.jiaoyishezhi, cl.openingdata, Datetime]  # 传递给交易函数用于交易
    # riqi = cl.get_riqi(1)
    # shijian = cl.get_shijian(1)
    理论持仓 = cl.openingdata['kaicangshuliang'] * cl.openingdata['kaicangzhuangtai']
    开仓价格 = cl.openingdata['kaicangjia']  # 开仓价格
    # 参数设置区
    开仓手数 = cl.jiaoyishezhi[5][0]  # 开仓数量
    均线周期 = cl.jiaoyishezhi[5][1]  # ma1周期
    # 指标计算区
    ma1 = ema_z(Close[-300:], 均线周期)
    # 交易逻辑执行区
    if 理论持仓 <= 0 and Open[-2] > ma1[-2] and Close[-2] > ma1[-2]:  # 开盘价和收盘价都要大于均线
        Buy(开仓手数, Open[-1], canshu)  # 平空开多
    else:
        if 理论持仓 >= 0 and Open[-2] < ma1[-2] and Close[-2] < ma1[-2]:  # 开盘价和收盘价都要小于均线
            SellShort(开仓手数, Open[-1], canshu)  # 平多开空

    return round(ma1[-2], 2), 'w', 开仓价格, 理论持仓  # 此处输出的指标会在k线图中和监控界面中显示


def 单均线策略预警_v1(cl):
    """
    单均线策略预警，开盘价，收盘价，都大于均线，预警开多，反之预警开空
    """
    # 数据提取区
    Open = cl.klines[0].open.values  # 开盘价np列表
    Close = cl.klines[0].close.values  # 收盘价np列表，Close[-1]这样为最新价
    Datetime = cl.klines[0].datetime.values  # 日期时间np列表，为时间戳
    canshu = [cl.jiaoyiqidong, cl.zhanghu, cl.jiaoyishezhi, cl.openingdata, Datetime]  # 传递给交易函数用于交易
    理论持仓 = cl.openingdata['kaicangshuliang'] * cl.openingdata['kaicangzhuangtai']
    开仓价格 = cl.openingdata['kaicangjia']  # 开仓价格
    # 参数设置区
    开仓手数 = cl.jiaoyishezhi[5][0]  # 开仓数量
    均线周期 = cl.jiaoyishezhi[5][1]  # ma1周期
    预警内容 = cl.jiaoyishezhi[5][2]  # 如填写螺纹
    # 软件名 = cl.jiaoyishezhi[5][3]  # 设置中的软件名
    heyue = cl.jiaoyishezhi[3][0]  # 交易的合约

    软件名 = cl.name.split(".")[0] + ".celue"

    # 指标计算区
    ma1 = ema_z(Close[-300:], 均线周期)
    # 交易逻辑执行区
    if 理论持仓 <= 0 and Open[-2] > ma1[-2] and Close[-2] > ma1[-2]:  # 开盘价和收盘价都要大于均线
        Buy_bxd(开仓手数, Open[-1], canshu)  # 平空开多
        shujuku.publish(软件名 + 'celue', heyue + ',' + 预警内容 + "开多")
        YuyinBobao(预警内容 + '开多')
    else:
        if 理论持仓 >= 0 and Open[-2] < ma1[-2] and Close[-2] < ma1[-2]:  # 开盘价和收盘价都要小于均线
            SellShort_bxd(开仓手数, Open[-1], canshu)  # 平多开空
            shujuku.publish(软件名 + 'celue', heyue + ',' + 预警内容 + "开空")
            YuyinBobao(预警内容 + '开空')

    return round(ma1[-2], 2), 'w', 开仓价格, 理论持仓  # 此处输出的指标会在k线图中和监控界面中显示


def 红三兵策略_v1(cl):
    """
    连续n根阳线开多，n根阴线开空
    """
    # 数据提取区
    Open = cl.klines[0].open.values  # 开盘价np列表
    High = cl.klines[0].high.values   # 最高价np列表
    Low = cl.klines[0].low.values  # 最低价np列表
    Close = cl.klines[0].close.values  # 收盘价np列表，Close[-1]这样为最新价
    Datetime = cl.klines[0].datetime.values  # 日期时间np列表，为时间戳
    canshu = [cl.jiaoyiqidong, cl.zhanghu, cl.jiaoyishezhi, cl.openingdata, Datetime]  # 传递给交易函数用于交易
    riqi = cl.get_riqi(1)
    shijian = cl.get_shijian(1)
    chicang = cl.openingdata['kaicangzhuangtai']  # 持仓状态和持仓数量

    # 参数设置区
    ss = cl.jiaoyishezhi[5][0]  # 开仓数量
    n1 = cl.jiaoyishezhi[5][1]  # 周期
    # 指标计算
    n = n1+1
    dd = np.sum(Close[-n:-1] > Open[-n:-1])  # 判断阳线数量
    xx = np.sum(Close[-n:-1] < Open[-n:-1])  # 判断阴线数量
    # 交易逻辑执行区
    if chicang <= 0 and dd >= n1:
        Buy(ss, Open[-1], canshu)  # 平空开多
    else:
        if chicang >= 0 and xx >= n1:
            SellShort(ss, Open[-1], canshu)  # 平多开空

    return dd, xx, 'w', 'w'   # 此处输出的指标会在k线图中和监控界面中显示


def 红三兵加均线策略_v1(cl):
    """
    连续n根阳线，且价格大于均线开多，n根阴线，且价格小于均线开空
    """
    # 数据提取区
    Open = cl.klines[0].open.values  # 开盘价np列表
    High = cl.klines[0].high.values   # 最高价np列表
    Low = cl.klines[0].low.values  # 最低价np列表
    Close = cl.klines[0].close.values  # 收盘价np列表，Close[-1]这样为最新价
    Datetime = cl.klines[0].datetime.values  # 日期时间np列表，为时间戳
    canshu = [cl.jiaoyiqidong, cl.zhanghu, cl.jiaoyishezhi, cl.openingdata, Datetime]  # 传递给交易函数用于交易
    riqi = cl.get_riqi(1)
    shijian = cl.get_shijian(1)
    chicang = cl.openingdata['kaicangzhuangtai']  # 持仓状态和持仓数量

    # 参数设置区
    ss = cl.jiaoyishezhi[5][0]  # 开仓数量
    n1 = cl.jiaoyishezhi[5][1]  # 周期
    均线周期 = cl.jiaoyishezhi[5][2]
    # 指标计算
    n = n1+1
    dd = np.sum(Close[-n:-1] > Open[-n:-1])  # 判断阳线数量
    xx = np.sum(Close[-n:-1] < Open[-n:-1])  # 判断阴线数量
    ma1 = ema_z(Close[-300:], 均线周期)
    # 交易逻辑执行区
    if chicang <= 0 and dd >= n1 and Open[-2] > ma1[-2] and Close[-2] > ma1[-2]:
        Buy(ss, Open[-1], canshu)  # 平空开多
    else:
        if chicang >= 0 and xx >= n1 and Open[-2] < ma1[-2] and Close[-2] < ma1[-2]:
            SellShort(ss, Open[-1], canshu)  # 平多开空

    return dd, xx,  ma1[-2], 0   # 此处输出的指标会在k线图中和监控界面中显示


def 多空线策略加atr通道出场_v1(cl):
    """
    多空线策略
    """
    # 数据提取区
    Open = cl.klines[0].open.values  # 开盘价np列表
    High = cl.klines[0].high.values   # 最高价np列表
    Low = cl.klines[0].low.values  # 最低价np列表
    Close = cl.klines[0].close.values  # 收盘价np列表，Close[-1]这样为最新价
    Datetime = cl.klines[0].datetime.values  # 日期时间np列表，为时间戳
    canshu = [cl.jiaoyiqidong, cl.zhanghu, cl.jiaoyishezhi, cl.openingdata, Datetime]  # 传递给交易函数用于交易
    chicang = cl.openingdata['kaicangzhuangtai']  # 持仓状态和持仓数量0,1或-1

    # 参数设置区
    ss = cl.jiaoyishezhi[5][0]  # 开仓数量
    慢线周期 = cl.jiaoyishezhi[5][1]
    牛熊线周期 = cl.jiaoyishezhi[5][2]
    慢线周期 = 10
    # 指标计算区
    # DKX计算
    MIB = (2 * Close + Low + Open + High) / 5
    MIB = MIB[:-1]
    XD = np.zeros(23)
    j = 20
    kk = 1
    for k in range(0, 20):
        lsbl = j * MIB[:-kk]
        XD = XD + lsbl[-23:]
        j = j - 1
        kk = kk + 1

    dkx = XD / 210
    慢线 = ma_z(dkx, 慢线周期)
    牛熊线 = ma_z(Close, 牛熊线周期)
    # 交易逻辑执行区
    # 开仓
    if chicang <= 0 and dkx[-2] > 慢线[-2] and dkx[-3] < 慢线[-3] and Close[-2]>牛熊线[-2]:
        Buy(ss, Open[-1], canshu)
        # print(ma1.iat[-2],ma2.iat[-2])
    else:
        if chicang >= 0  and dkx[-2] < 慢线[-2] and dkx[-3] > 慢线[-3] and Close[-2]<牛熊线[-2]:
            SellShort(ss,  Open[-1], canshu)

    # dkx平仓
    if chicang > 0 and dkx[-2] < 慢线[-2]:
        Sell(0, Open[-1], canshu)
    else:
        if chicang < 0  and dkx[-2] > 慢线[-2]:
            BuyToCover(0,  Open[-1], canshu)

    # atr通道平仓
    atr = atr_z(High, Low, Open, 10)
    atr上轨 = High[-2] + atr[-2]
    atr下轨 = Low[-2] - atr[-2]
    if chicang > 0 and Close[-2] < atr下轨:  # 平多
        Sell(0, Open[-1], canshu)
    else:
        if chicang < 0  and Close[-2] > atr下轨:  # 平空
            BuyToCover(0,  Open[-1], canshu)

    return dkx[-2], 慢线[-2], atr上轨, atr下轨


def 唐琪安通道_v1(cl):
    """
    此策略为唐琪安通道突破演示策略
    """
    # 数据提取区
    Open = cl.klines[0].open.values  # 开盘价np列表
    High = cl.klines[0].high.values   # 最高价np列表
    Low = cl.klines[0].low.values  # 最低价np列表
    Close = cl.klines[0].close.values  # 收盘价np列表，Close[-1]这样为最新价
    Datetime = cl.klines[0].datetime.values  # 日期时间np列表，为时间戳
    canshu = [cl.jiaoyiqidong, cl.zhanghu, cl.jiaoyishezhi, cl.openingdata, Datetime]  # 传递给交易函数用于交易
    chicang = cl.openingdata['kaicangzhuangtai'] *cl.openingdata['kaicangshuliang'] # 持仓状态和持仓数量
    kaicangjia = cl.openingdata['kaicangjia']  # 开仓价格

    # 参数设置区
    ss = cl.jiaoyishezhi[5][0]  # 开仓数量
    n1 = cl.jiaoyishezhi[5][1]+1  # 高点周期
    n2 = cl.jiaoyishezhi[5][2]+1  # 低点周期
    # print(ss,n1,n2)
    # 指标计算区
    gd = max(High[-n1:-1])
    dd = min(Low[-n2:-1])

    # 交易逻辑执行区
    if chicang <= 0 and High[-1] >= gd:
        Buy(ss, max(Open[-1], gd), canshu)
    else:
        if chicang >= 0 and Low[-1] <= dd:
            SellShort(ss, min(Open[-1], dd), canshu)

    return gd, dd, kaicangjia, 0


def 双通道突破回调加仓_v1(cl_sj):
    """
    双通道突破回调加仓策略，双通道为均线百分比包络线和收盘价n周期高低点。
    开仓：突破或跌破双通道。
    加仓：开仓后盈利达到百分之2，价格回调到5日均线，然后又突破高点就加仓1次，一直往复。
    平仓：开仓后的最高价回调百分之n平仓，或者反手。
    """
    # 数据初始化，
    Datetime = cl_sj.klines[0].datetime.values  # 时间转换为np列表
    canshu = [cl_sj.jiaoyiqidong, cl_sj.zhanghu, cl_sj.jiaoyishezhi, cl_sj.openingdata, Datetime]  # 传递给交易函数用于交易
    Open = cl_sj.klines[0].open.values
    high = cl_sj.klines[0].high.values
    low = cl_sj.klines[0].low.values
    close = cl_sj.klines[0].close.values
    chicang = cl_sj.openingdata['kaicangzhuangtai']
    chicang2 = chicang * cl_sj.openingdata['kaicangshuliang']
    kaicangjia = cl_sj.openingdata['kaicangjia']
    riqishijian = Datetime[-1]

    # 参数设置区
    SS = cl_sj.jiaoyishezhi[5][0]  # 开仓手数
    MAZQ = cl_sj.jiaoyishezhi[5][1]  # 均线周期
    MATDFD = cl_sj.jiaoyishezhi[5][2]  # MA通道幅度 %
    GDDZQ = cl_sj.jiaoyishezhi[5][3]+1  # 高低点周期
    JCMAZQ = cl_sj.jiaoyishezhi[5][4]  # 加仓均线周期
    PCFD = cl_sj.jiaoyishezhi[5][5]  # 平仓和保本幅度 %
    YLFD = cl_sj.jiaoyishezhi[5][6]  # 达到盈利幅度回调加仓

    # 全局变量的初始化，为空的时候执行
    if 'KCGD' not in cl_sj.sjb:  # 初始化时执行一次，用于初始化缓存字典
        cl_sj.sjb['KCGD'] = [close[-1]]  # 开仓上轨
        cl_sj.sjb['KCDD'] = [close[-1]]  # 开仓下轨
        cl_sj.sjb['JCMA'] = [close[-1]]  # 加仓ma
        cl_sj.sjb['ZGYL'] = 0  # 最高盈利
        cl_sj.sjb['PCJG'] = 0  # 平仓价格
        cl_sj.sjb['HTDMAJS'] = 0  # 回调到均线计数
        cl_sj.sjb['DDYLHJS'] = 0  # 盈利达到计数
        cl_sj.sjb['DQYL'] = 0  # 当前盈利
        cl_sj.sjb['kchgd'] = [0]  # 开仓后最高点
        cl_sj.sjb['kchdd'] = [999999]  # 开仓后最低点
        cl_sj.sjb['kchzq'] = 0  # 开仓后的周期
        cl_sj.sjb['kchbj'] = 1  # 开仓后的标记
        # cl_sj.sjb['fshkcbz'] = 0  # 反手或开仓标志，用于计算开仓后周期

    # 指标计算区
    if cl_sj.shangcishijian != Datetime[-1]:  # 更新k线时执行，一般用与计算指标
        MA = ma_z(close[:-1], MAZQ)
        cl_sj.sjb['JCMA'] = ma_z(close[:-1], JCMAZQ)
        MAG = MA[-1]+MA[-1]*(MATDFD*0.01)
        MAD = MA[-1]-MA[-1]*(MATDFD*0.01)
        UP = max(close[-GDDZQ:-1])
        DN = min(close[-GDDZQ:-1])
        cl_sj.sjb['KCGD'].append(max(MAG, UP))
        cl_sj.sjb['KCDD'].append(min(MAD, DN))
        cl_sj.sjb['kchbj'] = 1

        # 求开仓后的周期
        if chicang == 0:
            cl_sj.sjb['kchzq'] = 0
            cl_sj.sjb['fshkcbz'] = 0
        else:
            cl_sj.sjb['kchzq'] = cl_sj.sjb['kchzq'] + 1

    # 交易逻辑执行区
    # 开仓
    if chicang <= 0 and cl_sj.sjb['kchbj'] > 0 and high[-1] > cl_sj.sjb['KCGD'][-1]:  # 开多
        kaicangjia = max(cl_sj.sjb['KCGD'][-1], Open[-1])
        Buy(SS, kaicangjia, canshu)
        cl_sj.sjb['kchbj'] = 0
        cl_sj.sjb['kchzq'] = 0
        cl_sj.sjb['HTDMAJS'] = 0
        cl_sj.sjb['DDYLHJS'] = 0
        chicang = 1
        print(cl_sj.jiaoyishezhi[3][0], riqishijian, '开多：', SS, kaicangjia, '---------------------------------------')

    else:
        if chicang >= 0 and cl_sj.sjb['kchbj'] > 0 and low[-1] < cl_sj.sjb['KCDD'][-1]:  # 开空
            kaicangjia = min(cl_sj.sjb['KCDD'][-1], Open[-1])
            SellShort(SS, kaicangjia, canshu)
            cl_sj.sjb['kchbj'] = 0
            cl_sj.sjb['kchzq'] = 0
            cl_sj.sjb['HTDMAJS'] = 0
            cl_sj.sjb['DDYLHJS'] = 0
            chicang = -1
            print(cl_sj.jiaoyishezhi[3][0], riqishijian, '开空：', SS, kaicangjia, '-----------------------------------')
    # 加仓
    # 加仓条件计算
    if chicang == 1:
        DQYL = (high[-2] - kaicangjia) / kaicangjia * 100  # 当前盈利
        if DQYL > YLFD:
            cl_sj.sjb['DDYLHJS'] = 1  # 达到盈利后计数
        if close[-2] < cl_sj.sjb['JCMA'][-1] and cl_sj.sjb['DDYLHJS'] > 0:
            cl_sj.sjb['HTDMAJS'] = 1  # 价格回调到ma处
    else:
        if chicang == -1:
            DQYL = (kaicangjia - low[-2]) / kaicangjia * 100  # 当前盈利
            if DQYL > YLFD:
                cl_sj.sjb['DDYLHJS'] = 1  # 达到盈利后计数
            if close[-2] > cl_sj.sjb['JCMA'][-1] and cl_sj.sjb['DDYLHJS'] > 0:
                cl_sj.sjb['HTDMAJS'] = 1  # 价格回调到ma处
        else:
            DQYL = 0
            cl_sj.sjb['DDYLHJS'] = 0
            cl_sj.sjb['HTDMAJS'] = 0
        # print(riqishijian, DQYL)
    if chicang == 1 and high[-1]>cl_sj.sjb['KCGD'][-1] and cl_sj.sjb['HTDMAJS']>0 and cl_sj.sjb['DDYLHJS']>0:
        kaicangjia = max(cl_sj.sjb['KCGD'][-1], Open[-1])
        Buy_jjc(SS, kaicangjia, canshu)
        cl_sj.sjb['kchzq'] = 0
        cl_sj.sjb['HTDMAJS'] = 0
        cl_sj.sjb['DDYLHJS'] = 0
        print(cl_sj.jiaoyishezhi[3][0], riqishijian, '加多：', shujuku.hget(cl_sj.openingdata['name'], 'kaicangshuliang'), kaicangjia)
    else:
        if chicang == -1 and low[-1] < cl_sj.sjb['KCDD'][-1] and cl_sj.sjb['HTDMAJS'] > 0 and cl_sj.sjb['DDYLHJS'] > 0:
            kaicangjia = min(cl_sj.sjb['KCDD'][-1], Open[-1])
            SellShort_jjc(SS, kaicangjia, canshu)
            cl_sj.sjb['kchzq'] = 0
            cl_sj.sjb['HTDMAJS'] = 0
            cl_sj.sjb['DDYLHJS'] = 0
            print(cl_sj.jiaoyishezhi[3][0], riqishijian, '加空：', shujuku.hget(cl_sj.openingdata['name'], 'kaicangshuliang'), kaicangjia)

    # 平仓
    # 记录开仓后高低点
    if cl_sj.sjb['kchzq'] == 0:
        cl_sj.sjb['kchgd'] = kaicangjia
        cl_sj.sjb['kchdd'] = kaicangjia
    else:
        if cl_sj.sjb['kchzq'] > 0:
            cl_sj.sjb['kchgd'] = max(cl_sj.sjb['kchgd'], high[-1])
            cl_sj.sjb['kchdd'] = min(cl_sj.sjb['kchdd'], low[-1])

    # print(riqishijian, cl_sj.sjb['kchgd'], cl_sj.sjb['kchdd'])
    if chicang == 1:
        cl_sj.sjb['ZGYL'] = (cl_sj.sjb['kchgd']-kaicangjia)/kaicangjia*100
        cl_sj.sjb['PCJG'] = kaicangjia*(1-PCFD*0.01)  # 平仓价格计算
        if cl_sj.sjb['ZGYL'] > PCFD:
            cl_sj.sjb['PCJG'] = kaicangjia  # 最高盈利到达指定幅度，平仓价格调到指定价
    else:
        if chicang == -1:
            cl_sj.sjb['ZGYL'] = (kaicangjia-cl_sj.sjb['kchdd']) / kaicangjia * 100
            cl_sj.sjb['PCJG'] = kaicangjia * (1 + PCFD * 0.01)  # 平仓价格计算
            if cl_sj.sjb['ZGYL'] > PCFD:
                cl_sj.sjb['PCJG'] = kaicangjia  # 最高盈利到达指定幅度，平仓价格调到指定价
        else:
            cl_sj.sjb['ZGYL'] = close[-1]
            cl_sj.sjb['PCJG'] = close[-1]

    if chicang == 1 and cl_sj.sjb['kchzq'] > 0 and low[-1] <= cl_sj.sjb['PCJG']:
        kaicangjia = min(cl_sj.sjb['PCJG'], Open[-1])
        print(cl_sj.jiaoyishezhi[3][0], riqishijian, '平多：', shujuku.hget(cl_sj.openingdata['name'], 'kaicangshuliang'), kaicangjia)
        Sell(0, kaicangjia, canshu)
        cl_sj.sjb['kchzq'] = 0
    else:
        if chicang == -1 and cl_sj.sjb['kchzq'] > 0 and high[-1] >= cl_sj.sjb['PCJG']:
            kaicangjia = max(cl_sj.sjb['PCJG'], Open[-1])
            print(cl_sj.jiaoyishezhi[3][0], riqishijian, '平空：', shujuku.hget(cl_sj.openingdata['name'], 'kaicangshuliang'), kaicangjia)
            BuyToCover(0, kaicangjia, canshu)
            cl_sj.sjb['kchzq'] = 0

    return cl_sj.sjb['KCGD'][-1], cl_sj.sjb['KCDD'][-1], cl_sj.sjb['kchzq'], chicang2


def macd策略_diff(cl):
    """
    macd，diff策略，diff大于0平空开多，diff小于0平多开空。
    """
    # 数据提取区
    Open = cl.klines[0].open.values  # 开盘价np列表
    Close = cl.klines[0].close.values  # 收盘价np列表，Close[-1]这样为最新价
    Datetime = cl.klines[0].datetime.values  # 日期时间np列表，为时间戳
    canshu = [cl.jiaoyiqidong, cl.zhanghu, cl.jiaoyishezhi, cl.openingdata, Datetime]  # 传递给交易函数用于交易
    chicang = cl.openingdata['kaicangzhuangtai'] * cl.openingdata['kaicangshuliang']  # 持仓状态和持仓数量

    # 参数设置区
    手数 = cl.jiaoyishezhi[5][0]  # 开仓数量
    macdzq = cl.jiaoyishezhi[5][1]  # macd短周期
    macdzq2 = cl.jiaoyishezhi[5][2]  # macd长周期

    # 指标计算区
    # if cl.shangcishijian != Datetime[-1]:  # 更新k线时执行，一般用与计算指标
    diff = ema_z(Close[-300:], macdzq) - ema_z(Close[-300:], macdzq2)
    kctj_diff = round(diff[-2], 4)
    # 交易逻辑执行区
    if chicang <= 0 and kctj_diff > 0:
        Buy(手数, Open[-1], canshu)
    else:
        if chicang >= 0 and kctj_diff < 0:
            SellShort(手数, Open[-1], canshu)

    return 'w', kctj_diff, 'w', chicang


def ticktiaokong_gp1(cl):
    """
     tick跳空开仓高频策略，当个tick大于前一个tikc n跳，以对价开多。反之开空。
     止盈：开仓后挂n跳止盈
     止损：亏损n跳后以对价止损
     :param cl: 策略类
     :param cl.klines: k线数据，为df表，0层数据用klines[0]表示
     :param cl.openingdata: 交易数据，为字典，里面有持仓状态，理论持仓数量，开仓价格，开仓时间等
     :param cl.zhanghu: 账户列表
     :param cl.jiaoyishezhi: 为交易设置数据，算法交易，交易合约，其他功能参数都在里面
     :param cl.jiaoyiqidong: 是否启动了交易，为TRUS表示启动
     :return: 输出要在软件上显示的指标
     """
    # 数据提取区
    Open = cl.klines[0].open.values  # 开盘价np列表
    Datetime = cl.klines[0].datetime.values  # 日期时间np列表，为时间戳
    canshu = [cl.jiaoyiqidong, cl.zhanghu, cl.jiaoyishezhi, cl.openingdata, Datetime]  # 传递给交易函数用于交易
    chicangshuliang = cl.openingdata['kaicangshuliang']  # 理论持仓数量

    # 参数设置区
    ss = cl.jiaoyishezhi[5][0]  # 每次开仓数量，0为停止此策略
    tk = cl.jiaoyishezhi[5][1]  # 需跳空的值
    zy = cl.jiaoyishezhi[5][2]  # 止盈值
    zs = cl.jiaoyishezhi[5][3]  # 止损值

    zhbh = cl.jiaoyishezhi[0][0]  # 开仓账户编号

    # 初始化，初始化策略，和更新时运行一次
    if 'cczt' not in cl.sjb:  # 初始化时执行一次，用于初始化缓存字典
        cl.sjb['cczt'] = 0  # 持仓状态记录
        cl.sjb['stkzxj'] = 0  # 上一个tick最新价
        cl.sjb['xdid_kc'] = "8888"  # 开仓id
        cl.sjb['xdid_pc'] = "8888"  # 平仓id
        cl.sjb['hydx'] = cl.zhanghu[zhbh].get_zuixiaobiandong(cl.jiaoyishezhi[3][0])   # 最小变动单位
        cl.sjb['kcjg'] = 888
        cl.sjb['zy'] = zy * cl.sjb['hydx']  # 止盈点数转换为跳数
        cl.sjb['zs'] = zs * cl.sjb['hydx']  # 止损点数转换为跳数
        cl.sjb['tk'] = tk * cl.sjb['hydx']  # 跳空跳数
        cl.sjb['gdbz'] = False  # 挂单标志
        cl.sjb['yxgdbz'] = False  # 允许挂单标志
        cl.sjb['yxzsbz'] = False  # 允许止损标志
        cl.sjb['zscfbz'] = False  # 止损触发标志
        cl.sjb['zyjs'] = 0  # 止盈计数
        cl.sjb['zsjs'] = 0  # 止损计数
    tiaokong = 0 if cl.sjb['stkzxj'] == 0 else cl.tick['LastPrice'] - cl.sjb['stkzxj']  # tikc跳空值计算
    # 交易逻辑执行区
    if cl.jiaoyiqidong:
        cckcbz = False
        if cl.sjb['cczt'] == 0 and tiaokong > cl.sjb['tk']:
            cl.sjb['kcjg'] = cl.tick['Asks'][0][0]  # 对价下单
            cl.jiaoyishezhi[8][3] = cl.sjb['kcjg']
            cl.sjb['xdid_kc'] = cl.zhanghu[zhbh].kc_orders(cl.jiaoyishezhi, 1, ss)  # 开多
            cl.sjb['cczt'] = 1
            print('初次开多=', cl.jiaoyishezhi[3][0], cl.sjb['kcjg'])
            cckcbz = True
            cl.sjb['yxgdbz'] = True
            cl.sjb['yxzsbz'] = True
        else:
            if cl.sjb['cczt'] == 0 and tiaokong < -cl.sjb['tk']:
                cl.sjb['kcjg'] = cl.tick['Bids'][0][0]  # 对价下单
                cl.jiaoyishezhi[8][3] = cl.sjb['kcjg']
                cl.sjb['xdid_kc'] = cl.zhanghu[zhbh].kc_orders(cl.jiaoyishezhi, -1, ss)  # 开空
                cl.sjb['cczt'] = -1
                print('初次开空=', cl.jiaoyishezhi[3][0], cl.sjb['kcjg'])
                cckcbz = True
                cl.sjb['yxgdbz'] = True
                cl.sjb['yxzsbz'] = True

        # 账户仓位数据获取
        if cckcbz:  # 上个tick有下单暂停下，等待仓位返回
            time.sleep(0.3)
        dfcc = cl.zhanghu[zhbh].df_cc  # 对应账户持仓
        jyhe = cl.jiaoyishezhi[3][0]
        try:
            xb = dfcc[(dfcc.InstrumentID == jyhe)].index.tolist()[0]  # 求ZC的下标
            ccss = int(dfcc['Position'].at[xb])  # 需平仓手数
            ccfx = dfcc['Side'].at[xb]  # 需平仓持仓方向
        except:
            ccss = 0
            ccfx = 8
        if ccfx < 8:
            if ccfx == 1:
                ccss = -ccss
        # print('ccccc88=', jyhe, ccss, ccfx)
        # 账户持仓放入显示
        if ccss != chicangshuliang:
            MubiaoCangwei4_bxd(ccss, Open[-1], canshu)

        # 挂止盈单
        caiguadian = True
        if cl.sjb['cczt'] == 1 and ccss > 0 and cl.sjb['yxgdbz']:  # 挂多单止盈
            if cl.sjb['xdid_kc'] in cl.zhanghu[zhbh].order_dict:  # 已进行开仓挂单
                if cl.zhanghu[zhbh].order_dict[cl.sjb['xdid_kc']]['kcdsl'] == 0:  # # 可撤单数量为0
                    cl.jiaoyishezhi[8][3] = cl.sjb['kcjg']+cl.sjb['zy']
                    cl.sjb['xdid_pc'] = cl.zhanghu[zhbh].pc_orders(cl.jiaoyishezhi, 1, ccss)  # 多止盈平仓挂单
                    cl.sjb['gdbz'] = True
                    cl.sjb['yxgdbz'] = False
                    caiguadian = False
                    print('止盈挂单多=', cl.jiaoyishezhi[3][0], ccss, cl.jiaoyishezhi[8][3])
        else:
            if cl.sjb['cczt'] == -1 and ccss < 0 and cl.sjb['yxgdbz']:  # 挂多单止盈
                if cl.sjb['xdid_kc'] in cl.zhanghu[zhbh].order_dict:  # 已进行开仓挂单
                    if cl.zhanghu[zhbh].order_dict[cl.sjb['xdid_kc']]['kcdsl'] == 0:  # # 可撤单数量为0
                        cl.jiaoyishezhi[8][3] = cl.sjb['kcjg'] - cl.sjb['zy']
                        cl.sjb['xdid_pc'] = cl.zhanghu[zhbh].pc_orders(cl.jiaoyishezhi, -1, abs(ccss))  # 空止盈平仓挂单
                        cl.sjb['gdbz'] = True
                        cl.sjb['yxgdbz'] = False
                        caiguadian = False
                        print('止盈挂单空=', cl.jiaoyishezhi[3][0], ccss, cl.jiaoyishezhi[8][3])

        if cl.sjb['gdbz']:  # 止盈挂单后判断止盈挂单是否成交
            if cl.sjb['xdid_pc'] in cl.zhanghu[zhbh].order_dict:  # 已进行开仓挂单
                if cl.zhanghu[zhbh].order_dict[cl.sjb['xdid_pc']]['kcdsl'] == 0:  # 可撤单数量为0
                    cl.sjb['cczt'] = 0
                    cl.sjb['gdbz'] = False
                    cl.sjb['zyjs'] = cl.sjb['zyjs']+1
                    print('---------止盈=', cl.jiaoyishezhi[3][0], ccss, cl.jiaoyishezhi[8][3])

        # 止损
        if caiguadian and cl.sjb['yxzsbz']:
            if cl.sjb['cczt'] == 1 and ccss > 0:  # 多单止损
                zhisunjia = cl.sjb['kcjg']-cl.sjb['zs']
                if cl.tick['LastPrice'] <= zhisunjia:
                    if cl.sjb['xdid_pc'] in cl.zhanghu[zhbh].order_dict:  # 撤单后再发止损单
                        if cl.zhanghu[zhbh].order_dict[cl.sjb['xdid_pc']]['kcdsl'] != 0:
                            cl.zhanghu[zhbh].cd_orders(cl.sjb['xdid_pc'])  # 撤初次挂单
                            time.sleep(0.3)
                    cl.jiaoyishezhi[8][3] = cl.tick['Bids'][0][0]  # 对价下单
                    cl.sjb['xdid_pc'] = cl.zhanghu[zhbh].pc_orders(cl.jiaoyishezhi, 1, ccss)  # 对价平多
                    cl.sjb['zscfbz'] = True
                    cl.sjb['gdbz'] = False
                    cl.sjb['yxzsbz'] = False
                    cl.sjb['zsjs'] = cl.sjb['zsjs'] + 1
                    print('止损平多=', cl.jiaoyishezhi[3][0], ccss, cl.jiaoyishezhi[8][3])
            else:
                if cl.sjb['cczt'] == -1 and ccss < 0:  # 多单止损
                    zhisunjia = cl.sjb['kcjg']+cl.sjb['zs']
                    if cl.tick['LastPrice'] >= zhisunjia:
                        if cl.sjb['xdid_pc'] in cl.zhanghu[zhbh].order_dict:  # 撤单后再发止损单
                            if cl.zhanghu[zhbh].order_dict[cl.sjb['xdid_pc']]['kcdsl'] != 0:
                                cl.zhanghu[zhbh].cd_orders(cl.sjb['xdid_pc'])  # 撤初次挂单
                                time.sleep(0.3)
                        cl.jiaoyishezhi[8][3] = cl.tick['Asks'][0][0]  #对价下单
                        cl.sjb['xdid_pc'] = cl.zhanghu[zhbh].pc_orders(cl.jiaoyishezhi, -1, abs(ccss))  # 对价平多
                        cl.sjb['zscfbz'] = True
                        cl.sjb['gdbz'] = False
                        cl.sjb['yxzsbz'] = False
                        cl.sjb['zsjs'] = cl.sjb['zsjs'] + 1
                        print('止损平空=', cl.jiaoyishezhi[3][0], ccss, cl.jiaoyishezhi[8][3])

        if cl.sjb['zscfbz']:  # 止损触发后等止损成交后才允许再次开仓
            if cl.sjb['xdid_pc'] in cl.zhanghu[zhbh].order_dict:  # 已进行开仓挂单
                if cl.zhanghu[zhbh].order_dict[cl.sjb['xdid_pc']]['kcdsl'] == 0:  # 可撤单数量为0
                    cl.sjb['cczt'] = 0
                    cl.sjb['zscfbz'] = False

    cl.sjb['stkzxj'] = cl.tick['LastPrice']

    return cl.sjb['cczt'], cl.sjb['zyjs'], cl.sjb['zsjs'], tiaokong


def 定时清仓策略_v1(cl):
    """
     定时清仓策略
    """
    # 数据提取区
    Open = cl.klines[0].open.values  # 开盘价np列表
    Datetime = cl.klines[0].datetime.values  # 日期时间np列表，为时间戳
    canshu = [cl.jiaoyiqidong, cl.zhanghu, cl.jiaoyishezhi, cl.openingdata, Datetime]  # 传递给交易函数用于交易
    chicangshuliang = cl.openingdata['kaicangshuliang']  # 理论持仓数量
    shijian = int(time_to_datetime(Datetime[-1]).time().strftime("%H%M%S"))  # 当前时间
    # 参数设置区
    ss = cl.jiaoyishezhi[5][0]  # 每次开仓数量，0为停止此策略
    清仓时间 = cl.jiaoyishezhi[5][1]  # 时间格式为145500，用的k线时间
    pcpz = cl.jiaoyishezhi[5][2:]  # 排除不平仓的合约

    # zhanghu = cl.zhanghu[cl.jiaoyishezhi[0][0]]  # 开仓账户

    # 初始化，初始化策略，和更新时运行一次
    if 'cczt' not in cl.sjb:  # 初始化时执行一次，用于初始化缓存字典
        cl.sjb['cczt'] = 0  # 持仓状态记录

    # 指标计算区
    if cl.shangcishijian != Datetime[-1]:  # 更新k线时执行，一般用与计算指标
        if shijian == 210000:
            cl.sjb['cczt'] = 0

        if shijian == 清仓时间 and cl.sjb['cczt'] == 0 and cl.jiaoyiqidong:
            cl.sjb['cczt'] = 1
            cc = cl.zhanghu[cl.jiaoyishezhi[0][0]].df_cc
            for i in range(len(cc)):
                if cc['InstrumentID'].iat[i] not in pcpz:
                    if cc['Side'].iat[i] == 0:
                        cl.jiaoyishezhi[3][0] = cc['InstrumentID'].iat[i]  # 交易合约存入交易设置中
                        canshu = [cl.jiaoyiqidong, cl.zhanghu, deepcopy(cl.jiaoyishezhi), cl.openingdata, Datetime]  # 传递给交易函数用于交易
                        Sell_gzxd(int(cc['Position'].iat[i]), 8888, canshu)  # 平多
                        print(shijian, canshu[2][3][0], int(cc['Position'].iat[i]), '平多')
                    else:
                        if cc['Side'].iat[i] == 1:
                            cl.jiaoyishezhi[3][0] = cc['InstrumentID'].iat[i]  # 交易合约存入交易设置中
                            canshu = [cl.jiaoyiqidong, cl.zhanghu, deepcopy(cl.jiaoyishezhi), cl.openingdata, Datetime]  # 传递给交易函数用于交易
                            BuyToCover_gzxd(int(cc['Position'].iat[i]), 8888, canshu)  # 平多
                            print(shijian, canshu[2][3][0], int(cc['Position'].iat[i]), '平空')

    return cl.sjb['cczt'], shijian, 0, 0


def 刷新持仓_v1(cl):
    """
     定时刷新持仓，需要时放在策略最第一行
    """
    # 数据提取区
    # Open = cl.klines[0].open.values  # 开盘价np列表
    # Datetime = cl.klines[0].datetime.values  # 日期时间np列表，为时间戳
    # canshu = [cl.jiaoyiqidong, cl.zhanghu, cl.jiaoyishezhi, cl.openingdata, Datetime]  # 传递给交易函数用于交易
    # chicangshuliang = cl.openingdata['kaicangshuliang']  # 理论持仓数量
    # shijian = int(time_to_datetime(Datetime[-1]).time().strftime("%H%M%S"))  # 当前时间
    # 参数设置区
    ss = cl.jiaoyishezhi[5][0]  # 每次开仓数量，0为停止此策略
    备用1 = cl.jiaoyishezhi[5][1]  # 时间格式为145500，用的k线时间
    备用2 = cl.jiaoyishezhi[5][2]  # 排除不平仓的合约

    cl.zhanghu[cl.jiaoyishezhi[0][0]].query_positions()  # 刷新下持仓
    time.sleep(0.1)  #

    return 'w', 'w', 'w', 'w'

def 定时清仓留锁仓_v1(cl):
    """
     设定时间到达后全部清仓,保留锁仓，且该开平互转的合约需开平互转
    """
    # 数据提取区
    Open = cl.klines[0].open.values  # 开盘价np列表
    Datetime = cl.klines[0].datetime.values  # 日期时间np列表，为时间戳
    canshu = [cl.jiaoyiqidong, cl.zhanghu, cl.jiaoyishezhi, cl.openingdata, Datetime]  # 传递给交易函数用于交易
    chicangshuliang = cl.openingdata['kaicangshuliang']  # 理论持仓数量
    shijian = int(time_to_datetime(Datetime[-1]).time().strftime("%H%M%S"))  # 当前时间
    # 参数设置区
    ss = cl.jiaoyishezhi[5][0]  # 每次开仓数量，0为停止此策略
    清仓时间 = cl.jiaoyishezhi[5][1]  # 时间格式为145500，用的k线时间
    pcpz = cl.jiaoyishezhi[5][2:]  # 排除不平仓的合约

    # zhanghu = cl.zhanghu[cl.jiaoyishezhi[0][0]]  # 开仓账户

    # 初始化，初始化策略，和更新时运行一次
    if 'cczt' not in cl.sjb:  # 初始化时执行一次，用于初始化缓存字典
        cl.sjb['cczt'] = 0  # 持仓状态记录

    # 指标计算区
    if cl.shangcishijian != Datetime[-1]:  # 更新k线时执行，一般用与计算指标
        if shijian == 210000 or shijian == 93000:
            cl.sjb['cczt'] = 0

        if shijian == 清仓时间 and cl.sjb['cczt'] == 0 and cl.jiaoyiqidong:
            cl.sjb['cczt'] = 1
            cc = cl.zhanghu[cl.jiaoyishezhi[0][0]].df_cc.copy()
            # 从账户合并持仓为净持仓，并转换为列表
            duokong = []
            for i in range(len(cc)):
                if cc["Side"].iat[i] == 0:
                    duokong.append(1)
                else:
                    duokong.append(-1)
            cc["Position"] = cc["Position"] * duokong
            cc = cc.groupby('InstrumentID')['Position'].sum()  # 合并重复项算出净仓位
            cc = cc.reset_index()
            # cc["Position"] = cc["Position"].round()
            cc = cc[~cc['Position'].isin([0])]  # 删除总仓位零的行
            
            for i in range(len(cc)):
                if cc['InstrumentID'].iat[i] not in pcpz:
                    kpsl = int(cc['Position'].iat[i])
                    if kpsl > 0:
                        cl.jiaoyishezhi[3][0] = cc['InstrumentID'].iat[i]  # 交易合约存入交易设置中
                        canshu = [cl.jiaoyiqidong, cl.zhanghu, deepcopy(cl.jiaoyishezhi), cl.openingdata, Datetime]  # 传递给交易函数用于交易
                        Sell_gzxd(kpsl, 8888, canshu)  # 平多
                        print(shijian, canshu[2][3][0], int(cc['Position'].iat[i]), '平多')
                    else:
                        if kpsl < 0:
                            cl.jiaoyishezhi[3][0] = cc['InstrumentID'].iat[i]  # 交易合约存入交易设置中
                            canshu = [cl.jiaoyiqidong, cl.zhanghu, deepcopy(cl.jiaoyishezhi), cl.openingdata, Datetime]  # 传递给交易函数用于交易
                            BuyToCover_gzxd(abs(kpsl), 8888, canshu)  # 平多
                            print(shijian, canshu[2][3][0], int(cc['Position'].iat[i]), '平空')

    return cl.sjb['cczt'], shijian, 0, 0


def 多空市值计算_v1(cl):
    """
     计算多空市值，以及多空比值
     :param cl: 策略类
     :param cl.klines: k线数据，为df表，0层数据用klines[0]表示
     :param cl.openingdata: 交易数据，为字典，里面有持仓状态，理论持仓数量，开仓价格，开仓时间等
     :param cl.zhanghu: 账户列表
     :param cl.jiaoyishezhi: 为交易设置数据，算法交易，交易合约，其他功能参数都在里面
     :param cl.jiaoyiqidong: 是否启动了交易，为TRUS表示启动
     :return: 输出要在软件上显示的指标
     """
    # 数据提取区
    Open = cl.klines[0].open.values  # 开盘价np列表
    Datetime = cl.klines[0].datetime.values  # 日期时间np列表，为时间戳
    # canshu = [cl.jiaoyiqidong, cl.zhanghu, cl.jiaoyishezhi, cl.openingdata, Datetime]  # 传递给交易函数用于交易
    # chicangshuliang = cl.openingdata['kaicangshuliang']  # 理论持仓数量
    shijian = int(time_to_datetime(Datetime[-1]).time().strftime("%H%M%S"))  # 当前时间
    # 参数设置区
    ss = cl.jiaoyishezhi[5][0]  # 每次开仓数量，0为停止此策略
    备用 = cl.jiaoyishezhi[5][1] 
    备用 = cl.jiaoyishezhi[5][2:] 
    账户 = cl.zhanghu[cl.jiaoyishezhi[0][0]]  # 开仓账户

    # 初始化，初始化策略，和更新时运行一次
    if 'cczt' not in cl.sjb:  # 初始化时执行一次，用于初始化缓存字典
        cl.sjb['cczt'] = 0  # 持仓状态记录

    # 指标计算区
    if cl.shangcishijian != Datetime[-1]:  # 更新k线时执行，一般用与计算指标
        ...

    # 账户净仓位计算
    持仓 = 账户.df_cc.copy()
    持仓['duokong'] = 持仓['Side'].apply(lambda x: 1 if x == 0 else -1)
    持仓["Position"] = 持仓["Position"] * 持仓['duokong']
    持仓 = 持仓.groupby('InstrumentID')['Position'].sum()  # 合并重复项算出净仓位
    持仓 = 持仓.reset_index()

    # 多空市值计算
    多市值 = 0
    空市值 = 0
    多空比 = 0
    for i in range(len(持仓)):
        if 持仓['Position'].iat[i] > 0:
            多市值 += 持仓['Position'].iat[i]*账户.get_zuixinjia(持仓['InstrumentID'].iat[i])*账户.get_chengzhi(
                持仓['InstrumentID'].iat[i])
        else:
            if 持仓['Position'].iat[i] < 0:
                空市值 += abs(持仓['Position'].iat[i]) * 账户.get_zuixinjia(持仓['InstrumentID'].iat[i]) * 账户.get_chengzhi(
                    持仓['InstrumentID'].iat[i])

    if 空市值 != 0:
        多空比 = round(多市值/空市值, 4)

    return shijian, 多市值, 空市值, 多空比


def tick驱动策略测试_v1(cl):
    """
     测试tick驱动
     :param cl: 策略类
     :param cl.klines: k线数据，为df表，0层数据用klines[0]表示
     :param cl.openingdata: 交易数据，为字典，里面有持仓状态，理论持仓数量，开仓价格，开仓时间等
     :param cl.zhanghu: 账户列表
     :param cl.jiaoyishezhi: 为交易设置数据，算法交易，交易合约，其他功能参数都在里面
     :param cl.jiaoyiqidong: 是否启动了交易，为TRUS表示启动
     :return: 输出要在软件上显示的指标
     """
    # 数据提取区
    Open = cl.klines[0].open.values  # 开盘价np列表
    Datetime = cl.klines[0].datetime.values  # 日期时间np列表，为时间戳
    # canshu = [cl.jiaoyiqidong, cl.zhanghu, cl.jiaoyishezhi, cl.openingdata, Datetime]  # 传递给交易函数用于交易
    # chicangshuliang = cl.openingdata['kaicangshuliang']  # 理论持仓数量
    shijian = int(time_to_datetime(Datetime[-1]).time().strftime("%H%M%S"))  # 当前时间
    # 参数设置区
    ss = cl.jiaoyishezhi[5][0]  # 每次开仓数量，0为停止此策略
    备用 = cl.jiaoyishezhi[5][1]
    备用 = cl.jiaoyishezhi[5][2:]
    账户 = cl.zhanghu[cl.jiaoyishezhi[0][0]]  # 开仓账户

    # 初始化，初始化策略，和更新时运行一次
    if 'cczt' not in cl.sjb:  # 初始化时执行一次，用于初始化缓存字典
        cl.sjb['cczt'] = 0  # 持仓状态记录

    # 指标计算区
    if cl.shangcishijian != Datetime[-1]:  # 更新k线时执行，一般用与计算指标
        ...

    print(cl.tick)

    return cl.tick['LastPrice'], 0, 0, 0


def 指标编写示例_v1(cl):
    """
    指标编写示例
    """
    # 数据提取区
    OPEN = cl.klines[0].open.values  # 开盘价np列表
    CLOSE = cl.klines[0].close.values
    Datetime = cl.klines[0].datetime.values  # 日期时间np列表，为时间戳

    # 参数设置区
    ss = cl.jiaoyishezhi[5][0]  # 每次开仓数量，0为停止此策略
    备用 = cl.jiaoyishezhi[5][1]
    备用 = cl.jiaoyishezhi[5][2:]
    账户 = cl.zhanghu[cl.jiaoyishezhi[0][0]]  # 开仓账户

    # 初始化，初始化策略，和更新时运行一次
    if 'cczt' not in cl.sjb:  # 初始化时执行一次，用于初始化缓存字典
        cl.sjb['cczt'] = 0  # 持仓状态记录

    # 指标计算区
    if cl.shangcishijian != Datetime[-1]:  # 更新k线时执行，一般用与计算指标
        ...
    # MyTT库使用
    简单均线 = myttzb.MA(CLOSE, 8)
    移动平均 = myttzb.EMA(CLOSE, 8)
    是否金叉 = myttzb.CROSS(MA(CLOSE, 5), MA(CLOSE, 10))

    # 天勤ta使用
    简单均线2 = tqzb.MA(cl.klines[0], 8)
    移动平均2 = tqzb.EMA(cl.klines[0], 8)
    macd2 = tqzb.MACD(cl.klines[0], 12, 26, 9)

    # talib指标使用
    简单均线3 = talib.MA(CLOSE, 8)
    移动平均3 = talib.EMA(CLOSE, 8)
    macd3 = talib.MACD(CLOSE)

    return 0, 0, 0, 0




if __name__ == '__main__':
    df2 = load_data("ag_zl", 60, start_dt=20230101, fq=1)
    print(df2["heyue"])
    open_kxiantu()
